1장. 모델은 어디서 왔고 우리는 무엇을 만드나
출처: 『AI 엔지니어링』(Chip Huyen 지음, 한국어판) | 원서: AI Engineering (O'Reilly) 1장 대응
코드는 분위기만 — Python·import 같은 말은 몰라도 됩니다. 표의 '비유'와 '위험'만 봐도 충분해요.
이 장은 두 가지를 본다.
하나, 그 거대한 모델은 도대체 어디서 왔나.
둘, 그 모델 위에서 우리는 무엇을 만드나.
0장에서 배운 단어(모델·토큰·프롬프트·자기지도학습 등)만 알면 따라올 수 있다.
낯선 말이 나오면 0장 용어집으로 돌아가면 된다.
학습 목표
이 장을 끝내면 다음을 할 수 있다.
- 모델이 작은 것에서 거대한 것으로 커진 과정을 설명한다.
- 글을 이어 쓰는 모델과 빈칸을 채우는 모델을 구분한다.
- 우리가 만든 제품을 남이 못 베끼게 막는 방법을 설명한다.
0. 이 장의 새 단어
0장 용어집에 없던 말 세 개만 미리 풀어 둔다.
본문에서 이 셋이 나오면 여기로 돌아오면 된다.
각 단어는 [한 문장 뜻 + 일상비유 + 한 줄 예] 3종으로 적었다.
자기회귀 언어 모델(autoregressive language model)
한 문장 뜻 — 앞에 나온 말만 보고 다음 말을 한 칸씩 이어 쓰는 모델.
일상비유 — 끝말잇기. 지금까지 나온 말만 보고 다음 한 마디를 잇는다. 뒤에 뭐가 올지는 모른 채 앞만 보고 간다.
한 줄 예 —
# 앞 문장을 주면 뒤를 한 단어씩 이어 붙임
model.complete("오늘 날씨가") # → " 참 좋네요"
마스크 언어 모델(masked language model)
한 문장 뜻 — 문장 가운데를 뚫어 놓고, 앞뒤를 다 보면서 그 빈칸을 채우는 모델.
일상비유 — 빈칸 채우기 시험. "나는 ___ 을 좋아한다" 에서 앞("나는")과 뒤("을 좋아한다")를 다 읽고 가운데를 맞힌다.
한 줄 예 —
# 앞뒤를 다 보고 가운데 빈칸을 채움
model.fill("나는 [빈칸] 을 좋아한다") # → "김밥"
방어 가능성(defensibility)
한 문장 뜻 — 우리가 만든 제품을 경쟁사가 쉽게 못 베끼도록 막아 주는 힘.
일상비유 — 성을 둘러싼 해자(물길). 적이 쉽게 못 넘어오게 막아 준다. 해자가 없으면 누구나 똑같은 걸 만들어 따라온다.
한 줄 예 —
# 쌓인 사용자 데이터가 해자가 되어 따라오기 어렵게 함
moat = collect_user_data() # 남이 못 가진 우리만의 자료
(귀납 도입) 이런 적 있죠?
새 앱을 만들기로 했다.
"AI 앱이니까, 데이터 수백만 장 모아서 모델부터 만들어야지" 하고 6개월 일정을 잡았다.
그런데 옆 팀은 이미 만들어진 모델을 가져다 주말 만에 데모를 띄웠다.
같은 출발선이 아니었던 것이다.
옆 팀이 쓴 그 거대한 모델, 그게 바로 0장에서 본 파운데이션 모델이다.
그런데 이 모델은 처음부터 이렇게 크지 않았다.
아주 작게 시작해서, 한 가지 비법 덕분에 거대해졌다.
그 비법이 0장에서 배운 자기지도학습이다.
문장 하나를 손으로 가려 가며 "다음 말 뭐게?" 를 반복하면, 사람이 정답표를 안 만들어도 된다.
# 문장 하나에서 (입력 → 정답) 쌍이 저절로 만들어짐
"나는" → "김밥을" # 정답을 사람이 안 달아도 됨
정답표를 안 만드니, 인터넷에 있는 글을 통째로 학습에 쓸 수 있다.
글이 많아질수록 모델도 커졌고, 어느 순간 사람처럼 글을 쓰기 시작했다.
이렇게 커진 모델 위에서 무언가를 만드는 일, 그게 AI 엔지니어링이다.
이 장에서 딱 3가지만
TL;DR
- 모델은 작게 시작해 자기지도학습으로 커졌다. 사람이 정답표를 안 만들어도 되니, 인터넷 글을 통째로 먹고 거대해졌다.
- 글 모델은 두 종류다. 앞만 보고 이어 쓰는 모델(끝말잇기)과, 앞뒤를 다 보고 빈칸을 채우는 모델(빈칸 시험).
- 데모는 쉽고 진짜 제품은 어렵다. 그래서 남이 못 베끼게 막는 힘(방어 가능성)이 중요하고, 그 핵심은 쌓인 사용자 데이터다.
개념 1 — 모델은 자기지도학습으로 커졌다
망가지는 장면
모델을 처음부터 만들려고 사진 100만 장을 모았다.
그런데 사진마다 "이건 고양이", "이건 강아지" 하고 사람이 일일이 이름표를 달아야 했다.
이름표 다는 값만 수천만 원이 나왔다.
여기서 멈췄다. 이름표 비용이 너무 컸던 것이다.
일상비유
가림 학습이다.
"나는 김밥을 좋아한다" 라는 문장에서 뒷부분을 손으로 가린다.
"다음에 뭐가 올까?" 를 맞히면 된다.
정답이 이미 문장 안에 들어 있으니, 따로 이름표를 달 사람이 필요 없다.
| 비유 | 코드 | 위험 |
|---|---|---|
| 가림 학습(정답이 글 안에 있음) | "나는" → "김밥을" |
안전 — 사람 이름표 0, 인터넷 글 다 씀 |
| 이름표 일일이 달기(옛 방식) | label(img, "고양이") |
장당 비용 — 100만 장에 수천만 원 |
한 문장 정의 — 자기지도학습은 사람이 정답표를 안 만들어도 데이터 자체에서 정답을 뽑아 배우는 방식이며, 덕분에 인터넷 글을 통째로 먹고 모델이 거대해질 수 있었다.
가장 단순한 규칙 하나. 정답표를 사람이 만들 필요가 없으면, 그게 모델이 커진 비결이다.
예시 폭격
예시 ① — 완성예 (worked-example)
문장 하나에서 학습 거리가 여러 개 나온다.
"I love food" 한 줄을 보자.
# 한 문장에서 (입력 → 다음 말) 쌍이 줄줄이 나옴
"I" → "love"
"I love" → "food"
문장 하나로 학습 샘플 두 개를 공짜로 얻었다.
이름표를 달아 준 사람은 아무도 없다.
예시 ② — 부분완성 (빈칸 채우기)
이번엔 직접 채워 보자.
"나는 매운 떡볶이를" 이라는 문장이 있다.
# 빈칸을 채워 보세요
"나는" → "______" # 정답: 매운
"나는 매운" → "______" # 정답: 떡볶이를
정답이 문장 안에 이미 있으니, 가리고 맞히기만 하면 된다.
예시 ③ — 독립적용
이제 혼자 해 보자.
아무 문장이나 하나 떠올린다. 예: "주말에 비가 온다".
그 문장에서 (입력 → 다음 말) 쌍을 두 개 만들 수 있는가?
만들 수 있다면, 그 문장은 사람 이름표 없이도 학습 거리가 된 것이다.
이게 자기지도학습이 인터넷 글 전부를 먹을 수 있는 이유다.
미니 시나리오 — 이럴 때 이렇게
새 모델을 만들 데이터가 필요한데 이름표 달 돈이 없다.
이럴 때는 이름표가 필요 없는 자기지도 방식으로 글을 모으면 된다.
글 자체가 정답을 품고 있으니, 양만 늘리면 된다.
개념 2 — 글 모델은 두 종류다 (이어 쓰기 vs 빈칸 채우기)
망가지는 장면
문장 가운데가 뚫린 일이 생겼다.
"오늘 회의는 ___ 시에 시작" 에서 가운데를 맞히고 싶었다.
그런데 끝말잇기만 할 줄 아는 모델한테 시켰다.
이 모델은 앞("오늘 회의는")만 보고 가운데를 찍을 뿐, 뒤("시에 시작")를 못 봤다.
도구를 잘못 골랐던 것이다.
일상비유
두 가지 시험이 있다.
하나는 끝말잇기다. 앞에 나온 말만 보고 다음 한 마디를 잇는다.
다른 하나는 빈칸 채우기 시험이다. 앞뒤를 다 읽고 가운데를 맞힌다.
| 비유 | 코드 | 위험 |
|---|---|---|
| 끝말잇기(앞만 보고 이어 씀) | model.complete("오늘 날씨가") |
글 짓기엔 최강 — 가운데 빈칸엔 약함 |
| 빈칸 시험(앞뒤 보고 채움) | model.fill("나는 [빈칸] 좋아") |
빈칸·분류엔 강함 — 새 글 짓기엔 약함 |
한 문장 정의 — 자기회귀 언어 모델은 앞만 보고 다음 말을 이어 쓰는 모델이고, 마스크 언어 모델은 앞뒤를 다 보고 가운데 빈칸을 채우는 모델이다.
가장 단순한 규칙 하나. 새 글을 짓게 하려면 이어 쓰기 모델, 빈칸을 채우거나 분류하려면 빈칸 채우기 모델.
오늘 우리가 챗봇에서 보는 글짓기는 거의 다 이어 쓰기 모델 쪽이다.
예시 폭격
예시 ① — 완성예 (worked-example)
같은 입력을 두 모델에게 주면 하는 일이 다르다.
# 이어 쓰기 모델: 뒤를 새로 지어 붙임
model.complete("사느냐 죽느냐") # → ", 그것이 문제로다"
# 빈칸 채우기 모델: 가운데를 맞힘
model.fill("사느냐 [빈칸] 죽느냐") # → "또는"
하나는 새 문장을 짓고, 하나는 빠진 자리를 메운다.
예시 ② — 부분완성 (어느 쪽?)
다음 일에는 어떤 모델이 맞을지 골라 보자.
# 일 A: 이메일을 자동으로 이어서 써 줌 → ______ 모델
# 일 B: 리뷰가 칭찬인지 욕인지 분류함 → ______ 모델
A는 새 글을 짓는 일이니 이어 쓰기 모델.
B는 통째로 읽고 판정하는 일이니 빈칸 채우기 쪽 모델.
예시 ③ — 독립적용
이제 혼자 판단해 보자.
"문장 가운데 빠진 단어 하나를 복구하고 싶다."
앞만 보면 될까, 앞뒤를 다 봐야 할까?
앞뒤를 다 봐야 하니, 빈칸 채우기 모델이 맞다.
판단 기준은 딱 하나. 뒤쪽 정보가 필요하면 빈칸 채우기, 앞만으로 충분하면 이어 쓰기.
미니 시나리오 — 이럴 때 이렇게
고객 후기를 좋음·나쁨으로 자동 분류하고 싶다.
새 글을 짓는 게 아니라 통째로 읽고 판정하는 일이다.
이럴 때는 앞뒤를 다 보는 빈칸 채우기 모델 쪽이 잘 맞는다.
개념 3 — 남이 못 베끼게 막는 힘 (방어 가능성)
망가지는 장면
주말에 데모를 띄웠더니 반응이 좋았다.
"이거 대박이다" 하고 좋아했다.
그런데 한 달 뒤, 옆 회사가 똑같은 걸 내놨다.
우리도 남이 만든 모델을 가져다 썼고, 그쪽도 똑같은 모델을 가져다 썼다.
쓰는 모델이 같으니, 베끼기가 너무 쉬웠던 것이다.
일상비유
성을 둘러싼 해자(물길)다.
해자가 깊으면 적이 쉽게 못 넘어온다.
우리만 가진 것 — 사용자가 우리 앱을 쓰며 남긴 데이터 — 이 바로 해자다.
이 데이터는 우리한테만 쌓이니, 남이 못 가져간다.
| 비유 | 코드 | 위험 |
|---|---|---|
| 해자 있음(우리만의 데이터) | moat = collect_user_data() |
안전 — 남이 같은 데이터를 못 가짐 |
| 해자 없음(모델만 같음) | app = use(same_model) |
옆 회사가 똑같이 만들어 따라옴 |
한 문장 정의 — 방어 가능성은 우리가 만든 제품을 경쟁사가 쉽게 못 베끼도록 막아 주는 힘이며, 모델이 다 같은 세상에서는 우리한테만 쌓이는 사용자 데이터가 가장 든든한 해자다.
가장 단순한 규칙 하나. 모델만 같으면 누구나 베낀다. 우리한테만 쌓이는 데이터를 빨리 모아라.
예시 폭격
예시 ① — 완성예 (worked-example)
데이터가 쌓일수록 제품이 좋아지는 선순환을 보자.
# 더 많은 사용자 → 더 많은 데이터 → 더 나은 제품 → 더 많은 사용자
users = 100
data = collect_from(users) # 사용자가 쓸수록 데이터가 쌓임
better_app = improve(app, data) # 그 데이터로 제품이 좋아짐
# 좋아진 제품이 다시 사용자를 더 끌어옴
이 바퀴가 한 바퀴 돌 때마다 해자가 깊어진다.
예시 ② — 부분완성 (빈칸 채우기)
선순환 바퀴의 빠진 칸을 채워 보자.
# 사용자 ↑ → ______ ↑ → 제품 좋아짐 → 사용자 ↑ (반복)
# 빈칸 정답: 데이터
데이터가 가운데 톱니다.
데이터가 빠지면 바퀴가 안 돈다.
예시 ③ — 독립적용
이제 혼자 따져 보자.
두 회사가 똑같은 모델을 쓴다.
A 회사는 사용자 데이터를 모은다. B 회사는 안 모은다.
1년 뒤 누가 더 베끼기 어려운 제품을 갖게 될까?
데이터를 모은 A다. 그 데이터가 A만의 해자가 됐기 때문이다.
미니 시나리오 — 이럴 때 이렇게
작은 스타트업인데 큰 회사와 같은 모델을 쓴다.
모델로는 못 이긴다.
이럴 때는 시장에 먼저 들어가서, 사용자가 남기는 데이터부터 빨리 모으면 된다.
그 데이터가 시간이 지날수록 남이 못 넘는 해자가 된다.
정리
핵심 3줄.
모델은 자기지도학습 덕분에 사람 이름표 없이 인터넷 글을 먹고 거대해졌다.
글 모델은 둘 — 앞만 보고 이어 쓰는 모델(끝말잇기)과 앞뒤 보고 빈칸 채우는 모델(빈칸 시험).
데모는 쉽고 제품은 어려우니, 우리한테만 쌓이는 데이터로 남이 못 베끼게 막아야 한다.
가장 단순한 행동 규칙 하나만 들고 가자.
모델을 직접 만들지 말고 가져다 쓰되, 우리만의 데이터를 빨리 모아 해자를 파라.
다음 장 예고: 다음 장에서는 이 거대한 모델 안에서 무슨 일이 벌어지는지 한 꺼풀 들여다본다. (지금 몰라도 됩니다 — 다음 장에서 풀려요.)
클릭하거나 Space를 눌러 뒤집기